package hu.myai.api.indicators;

import hu.myai.model.TrendLineVO;

import java.util.ArrayList;
import java.util.List;

/**
 * @author bozbalint
 *
 */
abstract public class AbstractTrend {

    /**
     * It is a possibility to evaluate how useful the implementation of the
     * trend.
     * */
    private int score = 0;

    /**
     * a trend implementation has many trend lines. Trend channel contains 2 but
     * fibonacci contains more. This value contains a list of trend lines
     * */
    protected List<TrendLineVO> levelList = new ArrayList<TrendLineVO>();

    /**
     * returns the closest Support; the closest trend line which is just below
     * the tick. Tick timestamp must be set.
     * */
    public TrendLineVO getSupport(double y, int x) {
        TrendLineVO retValue = null;

        // get the closest support
        double minDistance = Double.NEGATIVE_INFINITY;
        for (TrendLineVO trendLine : levelList) {

            // distance is either positive or negative
            double distance = trendLine.getDistanceY(x, y);

            // get the closest trendline which is just below the the tick.
            if (distance > minDistance && distance < 0) {
                retValue = trendLine;
                minDistance = distance;
            }
            /*
             * // add statistical data to trend double distPct =
             * trendLine.getY(tick.getTimestamp()) / tick.getLow(); if
             * (Math.abs(distPct) < 0.01) trendLine.increaseTouch();
             */
        }
        return retValue;
    }

    /**
     * returns the closest Resistance; the closest trend line which is just
     * above the tick. Tick timestamp must be set.
     * */
    public TrendLineVO getResistance(double y, int x) {
        TrendLineVO retValue = null;

        // get the closest resistance
        double minDistance = Double.POSITIVE_INFINITY;
        for (TrendLineVO trendLine : levelList) {

            // distance is either positive or negative
            double distance = trendLine.getDistanceY(y, x);

            // get the closest trendline which is just below the the tick.
            if (distance < minDistance && distance > 0) {
                retValue = trendLine;
                minDistance = distance;
            }
            /*
             * // add statistical data to trend double distPct =
             * trendLine.getY(tick.getTimestamp()) / tick.getHigh(); if
             * (Math.abs(distPct) < 0.01) trendLine.increaseTouch();
             */
        }
        return retValue;
    }

    /**
     * Get how useful this trend. Score is a numeral representation of usability
     * */
    public int getScore() {
        return score;
    }

    /**
     * Set the score of the trend. If useful than increase the score otherwise
     * decrease.
     * */
    public void isUseful(boolean value) {
        if (value)
            score += 1;
        else
            score -= 1;
    }

    /**
     * @param y
     *            the price of the stock
     * @param x
     *            the timestamp
     * @param pct
     *            it is a percent; tolerance of the deviation
     * @return if the x,y point is on a trend line;
     */
    public boolean isOnTrendLine(double y, int x, int pct) {

        // get the closest resistance
        for (TrendLineVO trendLine : levelList) {

            double distance = Math.abs(trendLine.getDistanceY(y, x));

            // check the deviation
            // TODO configurable accepted deviation
            if (isInPct(distance, pct)) {
                return true;
            }
        }
        return false;
    }

    private boolean isInPct(double value, int limit) {
        return value < (1.0 + (limit / 100.0)) && value > (1.0 - (limit / 100.0));
    }
}
